﻿/* ================================================================================
<copyright file="IFWFLog.cs" company="The Framework Factory, LLC" lastWriteTime="12/05/2012 23:23:47 PM">
  Copyright (c) 2012 The Framework Factory, LLC.  All rights reserved.
</copyright>
=================================================================================== */
using System;
using System.Diagnostics.CodeAnalysis;

using log4net;
using log4net.Core;

namespace FWF.Logging
{
    /// <summary>
    /// Extended default log4net logging ( Debug / Info / Warn / Error / Fatal ) with more granular options based upon the
    /// already existing logging levels in log4net: ( Notice, Trace, Verbose, Severe )
    /// </summary>
    [SuppressMessage("Microsoft.Naming", "", Justification = "This is a interface named after the product name.")]
// ReSharper disable InconsistentNaming
    public interface IFWFLog : ILog
// ReSharper restore InconsistentNaming
    {
        /// <summary>
        /// Checks if this logger is enabled for the Notice level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Notice events, <c>false</c> otherwise.
        /// </value>
        /// <seealso cref="Notice(object)" />
        /// <remarks>
        ///   <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Notice statements.
        ///   </para>
        ///   <para> For some ILog interface <c>log</c>, when you write:</para>
        ///   <code lang="C#">
        /// log.Notice("This is entry number: " + i );
        ///   </code>
        ///   <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        ///   </para>
        ///   <para>
        /// If you are worried about speed (who isn't), then you should write:
        ///   </para>
        ///   <code lang="C#">
        /// if (log.IsNoticeEnabled)
        /// {
        /// log.Notice("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Notice enabled, you
        /// will incur the cost of evaluating whether the logger is Notice
        /// enabled twice. Once in <see cref="IsNoticeEnabled" /> and once in
        /// the <see cref="Notice(object)" />.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        ///   </para>
        ///   <para>Alternatively if your logger is available statically then the is Notice
        /// enabled state can be stored in a static variable like this:
        ///   </para>
        ///   <code lang="C#">
        /// private static readonly bool isNoticeEnabled = log.IsNoticeEnabled;
        ///   </code>
        ///   <para>
        /// Then when you come to log you can write:
        ///   </para>
        ///   <code lang="C#">
        /// if (isNoticeEnabled)
        /// {
        /// log.Notice("This is entry number: " + i );
        /// }
        ///   </code>
        ///   <para>
        /// This way the Notice enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        ///   </para>
        ///   <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        ///   </para>
        /// </remarks>
        bool IsNoticeEnabled
        {
            get;
        }

        /// <summary>
        /// Checks if this logger is enabled for the Trace level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Trace events, <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Trace statements.
        /// </para>
        /// <para> For some ILog interface <c>log</c>, when you write:</para>
        /// <code lang="C#">
        /// log.Trace("This is entry number: " + i );
        /// </code>
        /// <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        /// </para>
        /// <para>
        /// If you are worried about speed (who isn't), then you should write:
        /// </para>
        /// <code lang="C#">
        /// if (log.IsTraceEnabled)
        /// { 
        ///     log.Trace("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Trace enabled, you
        /// will incur the cost of evaluating whether the logger is Trace
        /// enabled twice. Once in <see cref="IsTraceEnabled"/> and once in
        /// the <see cref="Trace(object)"/>.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        /// </para>
        /// <para>Alternatively if your logger is available statically then the is Trace
        /// enabled state can be stored in a static variable like this:
        /// </para>
        /// <code lang="C#">
        /// private static readonly bool isTraceEnabled = log.IsTraceEnabled;
        /// </code>
        /// <para>
        /// Then when you come to log you can write:
        /// </para>
        /// <code lang="C#">
        /// if (isTraceEnabled)
        /// { 
        ///     log.Trace("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way the Trace enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        /// </para>
        /// <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        /// </para>
        /// </remarks>
        /// <seealso cref="Trace(object)"/>
        bool IsTraceEnabled
        {
            get;
        }

        /// <summary>
        /// Checks if this logger is enabled for the Verbose level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Verbose events, <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Verbose statements.
        /// </para>
        /// <para> For some ILog interface <c>log</c>, when you write:</para>
        /// <code lang="C#">
        /// log.Verbose("This is entry number: " + i );
        /// </code>
        /// <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        /// </para>
        /// <para>
        /// If you are worried about speed (who isn't), then you should write:
        /// </para>
        /// <code lang="C#">
        /// if (log.IsVerboseEnabled)
        /// { 
        ///     log.Verbose("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Verbose enabled, you
        /// will incur the cost of evaluating whether the logger is Verbose
        /// enabled twice. Once in <see cref="IsVerboseEnabled"/> and once in
        /// the <see cref="Verbose(object)"/>.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        /// </para>
        /// <para>Alternatively if your logger is available statically then the is Verbose
        /// enabled state can be stored in a static variable like this:
        /// </para>
        /// <code lang="C#">
        /// private static readonly bool isVerboseEnabled = log.IsVerboseEnabled;
        /// </code>
        /// <para>
        /// Then when you come to log you can write:
        /// </para>
        /// <code lang="C#">
        /// if (isVerboseEnabled)
        /// { 
        ///     log.Verbose("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way the Verbose enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        /// </para>
        /// <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        /// </para>
        /// </remarks>
        /// <seealso cref="Verbose(object)"/>
        bool IsVerboseEnabled
        {
            get;
        }

        /// <summary>
        /// Checks if this logger is enabled for the Severe level.
        /// </summary>
        /// <value>
        /// <c>true</c> if this logger is enabled for Severe events, <c>false</c> otherwise.
        /// </value>
        /// <remarks>
        /// <para>
        /// This function is intended to lessen the computational cost of
        /// disabled log Severe statements.
        /// </para>
        /// <para> For some ILog interface <c>log</c>, when you write:</para>
        /// <code lang="C#">
        /// log.Severe("This is entry number: " + i );
        /// </code>
        /// <para>
        /// You incur the cost constructing the message, string construction and concatenation in
        /// this case, regardless of whether the message is logged or not.
        /// </para>
        /// <para>
        /// If you are worried about speed (who isn't), then you should write:
        /// </para>
        /// <code lang="C#">
        /// if (log.IsSevereEnabled)
        /// { 
        ///     log.Severe("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way you will not incur the cost of parameter
        /// construction if debugging is disabled for <c>log</c>. On
        /// the other hand, if the <c>log</c> is Severe enabled, you
        /// will incur the cost of evaluating whether the logger is Severe
        /// enabled twice. Once in <see cref="IsSevereEnabled"/> and once in
        /// the <see cref="Severe(object)"/>.  This is an insignificant overhead
        /// since evaluating a logger takes about 1% of the time it
        /// takes to actually log. This is the preferred style of logging.
        /// </para>
        /// <para>Alternatively if your logger is available statically then the is Severe
        /// enabled state can be stored in a static variable like this:
        /// </para>
        /// <code lang="C#">
        /// private static readonly bool isSevereEnabled = log.IsSevereEnabled;
        /// </code>
        /// <para>
        /// Then when you come to log you can write:
        /// </para>
        /// <code lang="C#">
        /// if (isSevereEnabled)
        /// { 
        ///     log.Severe("This is entry number: " + i );
        /// }
        /// </code>
        /// <para>
        /// This way the Severe enabled state is only queried once
        /// when the class is loaded. Using a <c>private static readonly</c>
        /// variable is the most efficient because it is a run time constant
        /// and can be heavily optimized by the JIT compiler.
        /// </para>
        /// <para>
        /// Of course if you use a static readonly variable to
        /// hold the enabled state of the logger then you cannot
        /// change the enabled state at runtime to vary the logging
        /// that is produced. You have to decide if you need absolute
        /// speed or runtime flexibility.
        /// </para>
        /// </remarks>
        /// <seealso cref="Severe(object)"/>
        bool IsSevereEnabled
        {
            get;
        }

        /// <summary>
        /// Gets a value indicating whether this instance is statistics enabled.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is statistics enabled; otherwise, <c>false</c>.
        /// </value>
        bool IsStatisticsEnabled
        {
            get;
        }

        /// <summary>
        /// Logs the specified log event.
        /// </summary>
        /// <param name="logEvent">The log event.</param>
        void Log( LoggingEventData logEvent );

        /// <summary>
        /// Create a LoggingEvent component based upon the current context of the call.
        /// </summary>
        /// <returns></returns>
        LoggingEventData PrepareLogEvent( Type declaringType );

        /// <overloads>Log a message object with the Notice level.</overloads>
        /// <summary>
        /// Log a message object with the Notice level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <remarks>
        /// <para>
        /// This method first checks if this logger is <c>Notice</c>
        /// enabled by comparing the level of this logger with the 
        /// Notice level. If this logger is
        /// <c>Notice</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        /// <see cref="log4net.ObjectRenderer.IObjectRenderer"/>. It then 
        /// proceeds to call all the registered appenders in this logger 
        /// and also higher in the hierarchy depending on the value of 
        /// the additivity flag.
        /// </para>
        /// <para><b>WARNING</b> Note that passing an <see cref="Exception"/> 
        /// to this method will print the name of the <see cref="Exception"/> 
        /// but no stack trace. To print a stack trace use the 
        /// <see cref="Notice(object,Exception)"/> form instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Notice(object,Exception)"/>
        /// <seealso cref="IsNoticeEnabled"/>
        void Notice( object message );

        /// <summary>
        /// Log a message object with the Notice level including
        /// the stack trace of the <see cref="Exception"/> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack trace.</param>
        /// <remarks>
        /// <para>
        /// See the <see cref="Notice(object)"/> form for more detailed information.
        /// </para>
        /// </remarks>
        /// <seealso cref="Notice(object)"/>
        /// <seealso cref="IsNoticeEnabled"/>
        void Notice( object message, Exception exception );

        /// <overloads>Log a formatted string with the Notice level.</overloads>
        /// <summary>
        /// Logs a formatted message string with the Notice level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <remarks>
        /// <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </para>
        /// <para>
        /// This method does not take an <see cref="Exception"/> object to include in the
        /// log event. To pass an <see cref="Exception"/> use one of the <see cref="Notice(object,Exception)"/>
        /// methods instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Notice(object)"/>
        /// <seealso cref="IsNoticeEnabled"/>
        void NoticeFormat( string format, params object[] args );

        /// <overloads>Log a message object with the Trace level.</overloads>
        /// <summary>
        /// Log a message object with the Trace level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <remarks>
        /// <para>
        /// This method first checks if this logger is <c>Trace</c>
        /// enabled by comparing the level of this logger with the 
        /// Trace level. If this logger is
        /// <c>Trace</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        /// <see cref="log4net.ObjectRenderer.IObjectRenderer"/>. It then 
        /// proceeds to call all the registered appenders in this logger 
        /// and also higher in the hierarchy depending on the value of 
        /// the additivity flag.
        /// </para>
        /// <para><b>WARNING</b> Note that passing an <see cref="Exception"/> 
        /// to this method will print the name of the <see cref="Exception"/> 
        /// but no stack trace. To print a stack trace use the 
        /// <see cref="Trace(object,Exception)"/> form instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Trace(object,Exception)"/>
        /// <seealso cref="IsTraceEnabled"/>
        void Trace( object message );

        /// <summary>
        /// Log a message object with the Trace level including
        /// the stack trace of the <see cref="Exception"/> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack trace.</param>
        /// <remarks>
        /// <para>
        /// See the <see cref="Trace(object)"/> form for more detailed information.
        /// </para>
        /// </remarks>
        /// <seealso cref="Trace(object)"/>
        /// <seealso cref="IsTraceEnabled"/>
        void Trace( object message, Exception exception );

        /// <overloads>Log a formatted string with the Trace level.</overloads>
        /// <summary>
        /// Logs a formatted message string with the Trace level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <remarks>
        /// <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </para>
        /// <para>
        /// This method does not take an <see cref="Exception"/> object to include in the
        /// log event. To pass an <see cref="Exception"/> use one of the <see cref="Trace(object,Exception)"/>
        /// methods instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Trace(object)"/>
        /// <seealso cref="IsTraceEnabled"/>
        void TraceFormat( string format, params object[] args );

        /// <overloads>Log a message object with the Verbose level.</overloads>
        /// <summary>
        /// Log a message object with the Verbose level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <remarks>
        /// <para>
        /// This method first checks if this logger is <c>Verbose</c>
        /// enabled by comparing the level of this logger with the 
        /// Verbose level. If this logger is
        /// <c>Verbose</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        /// <see cref="log4net.ObjectRenderer.IObjectRenderer"/>. It then 
        /// proceeds to call all the registered appenders in this logger 
        /// and also higher in the hierarchy depending on the value of 
        /// the additivity flag.
        /// </para>
        /// <para><b>WARNING</b> Note that passing an <see cref="Exception"/> 
        /// to this method will print the name of the <see cref="Exception"/> 
        /// but no stack Verbose. To print a stack Verbose use the 
        /// <see cref="Verbose(object,Exception)"/> form instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Verbose(object,Exception)"/>
        /// <seealso cref="IsVerboseEnabled"/>
        void Verbose( object message );

        /// <summary>
        /// Log a message object with the Verbose level including
        /// the stack Verbose of the <see cref="Exception"/> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack Verbose.</param>
        /// <remarks>
        /// <para>
        /// See the <see cref="Verbose(object)"/> form for more detailed information.
        /// </para>
        /// </remarks>
        /// <seealso cref="Verbose(object)"/>
        /// <seealso cref="IsVerboseEnabled"/>
        void Verbose( object message, Exception exception );

        /// <overloads>Log a formatted string with the Verbose level.</overloads>
        /// <summary>
        /// Logs a formatted message string with the Verbose level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <remarks>
        /// <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </para>
        /// <para>
        /// This method does not take an <see cref="Exception"/> object to include in the
        /// log event. To pass an <see cref="Exception"/> use one of the <see cref="Verbose(object,Exception)"/>
        /// methods instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Verbose(object)"/>
        /// <seealso cref="IsVerboseEnabled"/>
        void VerboseFormat( string format, params object[] args );

        /// <overloads>Log a message object with the Severe level.</overloads>
        /// <summary>
        /// Log a message object with the Severe level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <remarks>
        /// <para>
        /// This method first checks if this logger is <c>Severe</c>
        /// enabled by comparing the level of this logger with the 
        /// Severe level. If this logger is
        /// <c>Severe</c> enabled, then it converts the message object
        /// (passed as parameter) to a string by invoking the appropriate
        /// <see cref="log4net.ObjectRenderer.IObjectRenderer"/>. It then 
        /// proceeds to call all the registered appenders in this logger 
        /// and also higher in the hierarchy depending on the value of 
        /// the additivity flag.
        /// </para>
        /// <para><b>WARNING</b> Note that passing an <see cref="Exception"/> 
        /// to this method will print the name of the <see cref="Exception"/> 
        /// but no stack Severe. To print a stack Severe use the 
        /// <see cref="Severe(object,Exception)"/> form instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Severe(object,Exception)"/>
        /// <seealso cref="IsSevereEnabled"/>
        void Severe( object message );

        /// <summary>
        /// Log a message object with the Severe level including
        /// the stack Severe of the <see cref="Exception"/> passed
        /// as a parameter.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <param name="exception">The exception to log, including its stack Severe.</param>
        /// <remarks>
        /// <para>
        /// See the <see cref="Severe(object)"/> form for more detailed information.
        /// </para>
        /// </remarks>
        /// <seealso cref="Severe(object)"/>
        /// <seealso cref="IsSevereEnabled"/>
        void Severe( object message, Exception exception );

        /// <overloads>Log a formatted string with the Severe level.</overloads>
        /// <summary>
        /// Logs a formatted message string with the Severe level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <remarks>
        /// <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </para>
        /// <para>
        /// This method does not take an <see cref="Exception"/> object to include in the
        /// log event. To pass an <see cref="Exception"/> use one of the <see cref="Severe(object,Exception)"/>
        /// methods instead.
        /// </para>
        /// </remarks>
        /// <seealso cref="Severe(object)"/>
        /// <seealso cref="IsSevereEnabled"/>
        void SevereFormat( string format, params object[] args );

        /// <summary>
        /// Log a message object with the Statistic level.
        /// </summary>
        /// <param name="message">The message object to log.</param>
        /// <remarks>
        /// <para>
        /// See the <see cref="Statistic(object)"/> form for more detailed information.
        /// </para>
        /// </remarks>
        /// <seealso cref="Statistic(object)"/>
        /// <seealso cref="IsStatisticsEnabled"/>
        void Statistic( object message );

        /// <summary>
        /// Logs a formatted message string with the Statistic level.
        /// </summary>
        /// <param name="format">A String containing zero or more format items</param>
        /// <param name="args">An Object array containing zero or more objects to format</param>
        /// <remarks>
        /// <para>
        /// The message is formatted using the <c>String.Format</c> method. See
        /// <see cref="String.Format(string, object[])"/> for details of the syntax of the format string and the behavior
        /// of the formatting.
        /// </para>
        /// </remarks>
        /// <seealso cref="Statistic(object)"/>
        /// <seealso cref="IsStatisticsEnabled"/>
        void StatisticFormat( string format, params object[] args );

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ifTrue">if set to <c>true</c> [if true].</param>
        /// <param name="message">The message.</param>
        void WarnIf( bool ifTrue, string message );
    }
}
